export class List<T> {
  private arr: T[] = [];

  public constructor(arr?: T[]) {
    if (arr) {
      this.arr = arr;
    }
  }

  public Get(index: number): T {
    return this.arr[index];
  }

  public get Count(): number {
    return this.arr.length;
  }

  public Add(data: T) {
    this.arr.push(data);
  }

  public AddRange(arr: T[]) {
    this.arr = this.arr.concat(arr);
  }

  public Clear() {
    while (this.arr.length > 0) {
      this.arr.pop();
    }
  }

  public Remove(data: T): boolean {
    if (data) {
      let index = this.arr.indexOf(data);
      if (index >= 0) this.arr.splice(index, 1);
    }
    return false;
  }

  public Insert(index: number, item: T) {
    this.arr.splice(index, 0, item);
  }

  public Sort() {
    this.arr.sort();
  }

  public Reverse() {
    this.arr.reverse();
  }

  public ToArray(): T[] {
    let result: T[] = [];
    //result.concat(this.arr);
    return this.arr;
  }

  public Contains(item: T): boolean {
    return this.arr.indexOf(item) >= 0;
  }

  public IndexOf(item: T): number {
    return this.arr.indexOf(item);
  }

  public LastIndexOf(item: T): number {
    return this.arr.lastIndexOf(item);
  }

  public ToString(): string {
    let result: string = '';
    for (let item of this.arr) {
      result += `${item} `;
    }
    return result;
  }
}

export class pointDataCollect {
  attribute: string = '';
  result: any = [];
}

export enum EUnormals {
  Out_Of_ControlLine,
  _9Points_Continous_One_side,
  _6Points_Continous_Increase_Or_Decreas,
  _14Points_Sawtooth,
  _2of3Continous_points_Out_Of_B_Area,
  _4of5Continous_points_Out_Of_C_Area,
  _15Points_Continous_Inside_C_Area,
  _8Points_Continous_Biside_But_Out_Of_C_Area
}
export class SUnormals {
  pointIndex: number;
  UnNormType: EUnormals;
  value: number;
  constructor(pointIndex: number, UnNormType: EUnormals, value: number) {
    this.pointIndex = pointIndex;
    this.UnNormType = UnNormType;
    this.value = value;
  }
}

export function SpcChartAbnormalJudgementForBrokenLine(
  ucl: number[],
  lcl: number[],
  cl: number,
  sigma: number[],
  spcList: number[],
  category: number,
  sigmaL: number[] = []
): List<SUnormals> {
  var unormList = new List<SUnormals>();
  var unmPoints = new List<number>();

  let type1 = category & 1;
  if (type1 == 1) {
    //Out_Of_ControlLine
    for (let i = 0; i < spcList.length; i++) {
      if (spcList[i] > ucl[i] || spcList[i] < lcl[i]) {
        let unnormal = new SUnormals(i, EUnormals.Out_Of_ControlLine, spcList[i]);
        unormList.Add(unnormal);
      }
    }
  }

  let type2 = category & 2;
  if (type2 == 2) {
    //_9Points_Continous_One_side
    let tempunornals = SpcChartAbnormalJudgement(0, 0, cl, 0, spcList, 2, 0).ToArray();
    unormList.AddRange(tempunornals);
  }

  let type3 = category & 4;
  if (type3 == 4) {
    //_6Points_Continous_Increase_Or_Decreas
    let tempunornals = SpcChartAbnormalJudgement(0, 0, cl, 0, spcList, 4, 0).ToArray();
    unormList.AddRange(tempunornals);
  }

  let type4 = category & 8;
  if (type4 == 8) {
    //_14Points_Sawtooth
    let tempunornals = SpcChartAbnormalJudgement(0, 0, cl, 0, spcList, 8, 0).ToArray();
    unormList.AddRange(tempunornals);
  }

  let type5 = category & 16;
  if (type5 == 16) {
    //_2of3Continous_points_Out_Of_B_Area
    unmPoints.Clear();
    for (let i = 2; i < spcList.length; i++) {
      let count = 0;
      for (let k = i - 2; k <= i; k++) {
        if (spcList[k] > cl + 2 * sigma[k]) {
          count++;
        }
      }
      if (count >= 2) {
        unmPoints.Add(i);
      }
      count = 0;
      for (let k = i - 2; k <= i; k++) {
        if (spcList[k] < cl - 2 * sigmaL[k]) {
          count++;
        }
      }
      if (count >= 2) {
        unmPoints.Add(i);
      }
    }
    if (unmPoints.Count > 0) {
      for (let j = 0; j < unmPoints.Count; j++) {
        let subscript: number = unmPoints.Get(j);
        let unnormal = new SUnormals(subscript, EUnormals._2of3Continous_points_Out_Of_B_Area, spcList[subscript]);
        unormList.Add(unnormal);
      }
    }
  }

  let type6 = category & 32;
  if (type6 == 32) {
    //_4of5Continous_points_Out_Of_C_Area
    unmPoints.Clear();
    for (let i = 4; i < spcList.length; i++) {
      let count = 0;
      for (let k = i - 4; k <= i; k++) {
        if (spcList[k] > cl + sigma[k]) {
          count++;
        }
      }
      if (count >= 4) {
        unmPoints.Add(i);
      }
      count = 0;
      for (let k = i - 4; k <= i; k++) {
        if (spcList[k] < cl - sigmaL[k]) {
          count++;
        }
      }
      if (count >= 4) {
        unmPoints.Add(i);
      }
    }
    if (unmPoints.Count > 0) {
      for (let j = 0; j < unmPoints.Count; j++) {
        let subscript: number = unmPoints.Get(j);
        let unnormal = new SUnormals(subscript, EUnormals._4of5Continous_points_Out_Of_C_Area, spcList[subscript]);
        unormList.Add(unnormal);
      }
    }
  }

  let type7 = category & 64;
  if (type7 == 64) {
    //_15Points_Continous_Inside_C_Area
    unmPoints.Clear();
    for (let i = 0; i < spcList.length; i++) {
      if (spcList[i] > cl + sigma[i] || spcList[i] < cl - sigmaL[i]) {
        if (unmPoints.Count >= 15) {
          for (let j = 14; j < unmPoints.Count; j++) {
            let subscript: number = unmPoints.Get(j);
            let unnormal = new SUnormals(subscript, EUnormals._15Points_Continous_Inside_C_Area, spcList[subscript]);
            unormList.Add(unnormal);
          }
        }
        unmPoints.Clear();
      } else {
        unmPoints.Add(i);
      }
    }
    if (unmPoints.Count >= 15) {
      if (unmPoints.Count >= 15) {
        for (let j = 14; j < unmPoints.Count; j++) {
          let subscript: number = unmPoints.Get(j);
          let unnormal = new SUnormals(subscript, EUnormals._15Points_Continous_Inside_C_Area, spcList[subscript]);
          unormList.Add(unnormal);
        }
      }
    }
  }

  let type8 = category & 128;
  if (type8 == 128) {
    //_8Points_Continous_Biside_But_Out_Of_C_Area
    unmPoints.Clear();
    for (let i = 0; i < spcList.length; i++) {
      if (spcList[i] < cl + sigma[i] && spcList[i] > cl - sigmaL[i]) {
        if (unmPoints.Count >= 8) {
          for (let j = 7; j < unmPoints.Count; j++) {
            let subscript: number = unmPoints.Get(j);
            let unnormal = new SUnormals(subscript, EUnormals._8Points_Continous_Biside_But_Out_Of_C_Area, spcList[subscript]);
            unormList.Add(unnormal);
          }
        }
        unmPoints.Clear();
      } else {
        unmPoints.Add(i);
      }
    }
    if (unmPoints.Count >= 8) {
      for (let j = 7; j < unmPoints.Count; j++) {
        let subscript: number = unmPoints.Get(j);
        let unnormal = new SUnormals(subscript, EUnormals._8Points_Continous_Biside_But_Out_Of_C_Area, spcList[subscript]);
        unormList.Add(unnormal);
      }
    }
  }

  return unormList;
}

export function SpcChartAbnormalJudgement(
  ucl: number,
  lcl: number,
  cl: number,
  sigma: number,
  spcList: number[],
  category: number,
  sigmaL: number = 0
): List<SUnormals> {
  var unormList = new List<SUnormals>();
  var unmPoints = new List<number>();

  let type1 = category & 1;
  if (type1 == 1) {
    //Out_Of_ControlLine
    for (let i = 0; i < spcList.length; i++) {
      if (spcList[i] > ucl || spcList[i] < lcl) {
        let unnormal = new SUnormals(i, EUnormals.Out_Of_ControlLine, spcList[i]);
        unormList.Add(unnormal);
      }
    }
  }

  let type2 = category & 2;
  if (type2 == 2) {
    //_9Points_Continous_One_side
    for (let i = 0; i < spcList.length; i++) {
      if (i == 0) {
        unmPoints.Add(i);
      } else {
        if ((spcList[i] - cl) * (spcList[i - 1] - cl) < 0) {
          if (unmPoints.Count >= 9) {
            for (let j = 8; j < unmPoints.Count; j++) {
              let subscript: number = unmPoints.Get(j);
              let unnormal = new SUnormals(subscript, EUnormals._9Points_Continous_One_side, spcList[subscript]);
              unormList.Add(unnormal);
            }
          }
          unmPoints.Clear();
        }
        unmPoints.Add(i);
      }
    }
    if (unmPoints.Count >= 9) {
      for (let j = 8; j < unmPoints.Count; j++) {
        let subscript: number = unmPoints.Get(j);
        let unnormal = new SUnormals(subscript, EUnormals._9Points_Continous_One_side, spcList[subscript]);
        unormList.Add(unnormal);
      }
    }
  }

  let type3 = category & 4;
  if (type3 == 4) {
    //_6Points_Continous_Increase_Or_Decreas
    unmPoints.Clear();
    for (let i = 0; i < spcList.length; i++) {
      if (i < 2) {
        unmPoints.Add(i);
      } else {
        if ((spcList[i] - spcList[i - 1]) * (spcList[i - 1] - spcList[i - 2]) <= 0) {
          if (unmPoints.Count >= 6) {
            for (let j = 5; j < unmPoints.Count; j++) {
              let subscript: number = unmPoints.Get(j);
              let unnormal = new SUnormals(subscript, EUnormals._6Points_Continous_Increase_Or_Decreas, spcList[subscript]);
              unormList.Add(unnormal);
            }
          }
          unmPoints.Clear();
          unmPoints.Add(i - 1);
        }
        unmPoints.Add(i);
      }
    }
    if (unmPoints.Count >= 6) {
      for (let j = 5; j < unmPoints.Count; j++) {
        let subscript: number = unmPoints.Get(j);
        let unnormal = new SUnormals(subscript, EUnormals._6Points_Continous_Increase_Or_Decreas, spcList[subscript]);
        unormList.Add(unnormal);
      }
    }
  }

  let type4 = category & 8;
  if (type4 == 8) {
    //_14Points_Sawtooth
    unmPoints.Clear();
    for (let i = 0; i < spcList.length; i++) {
      if (i < 2) {
        unmPoints.Add(i);
      } else {
        if ((spcList[i] - spcList[i - 1]) * (spcList[i - 1] - spcList[i - 2]) > 0) {
          if (unmPoints.Count >= 14) {
            for (let j = 13; j < unmPoints.Count; j++) {
              let subscript: number = unmPoints.Get(j);
              let unnormal = new SUnormals(subscript, EUnormals._14Points_Sawtooth, spcList[subscript]);
              unormList.Add(unnormal);
            }
          }
          unmPoints.Clear();
          unmPoints.Add(i - 1);
        }
        unmPoints.Add(i);
      }
    }
    if (unmPoints.Count >= 14) {
      for (let j = 13; j < unmPoints.Count; j++) {
        let subscript: number = unmPoints.Get(j);
        let unnormal = new SUnormals(subscript, EUnormals._14Points_Sawtooth, spcList[subscript]);
        unormList.Add(unnormal);
      }
    }
  }

  let type5 = category & 16;
  if (type5 == 16) {
    //_2of3Continous_points_Out_Of_B_Area
    unmPoints.Clear();
    for (let i = 2; i < spcList.length; i++) {
      let count = 0;
      for (let k = i - 2; k <= i; k++) {
        if (spcList[k] > cl + 2 * sigma) {
          count++;
        }
      }
      if (count >= 2) {
        unmPoints.Add(i);
      }
      count = 0;
      for (let k = i - 2; k <= i; k++) {
        if (spcList[k] < cl - 2 * sigmaL) {
          count++;
        }
      }
      if (count >= 2) {
        unmPoints.Add(i);
      }
    }
    if (unmPoints.Count > 0) {
      for (let j = 0; j < unmPoints.Count; j++) {
        let subscript: number = unmPoints.Get(j);
        let unnormal = new SUnormals(subscript, EUnormals._2of3Continous_points_Out_Of_B_Area, spcList[subscript]);
        unormList.Add(unnormal);
      }
    }
  }

  let type6 = category & 32;
  if (type6 == 32) {
    //_4of5Continous_points_Out_Of_C_Area
    unmPoints.Clear();
    for (let i = 4; i < spcList.length; i++) {
      let count = 0;
      for (let k = i - 4; k <= i; k++) {
        if (spcList[k] > cl + sigma) {
          count++;
        }
      }
      if (count >= 4) {
        unmPoints.Add(i);
      }
      count = 0;
      for (let k = i - 4; k <= i; k++) {
        if (spcList[k] < cl - sigmaL) {
          count++;
        }
      }
      if (count >= 4) {
        unmPoints.Add(i);
      }
    }
    if (unmPoints.Count > 0) {
      for (let j = 0; j < unmPoints.Count; j++) {
        let subscript: number = unmPoints.Get(j);
        let unnormal = new SUnormals(subscript, EUnormals._4of5Continous_points_Out_Of_C_Area, spcList[subscript]);
        unormList.Add(unnormal);
      }
    }
  }

  let type7 = category & 64;
  if (type7 == 64) {
    //_15Points_Continous_Inside_C_Area
    unmPoints.Clear();
    for (let i = 0; i < spcList.length; i++) {
      if (spcList[i] > cl + sigma || spcList[i] < cl - sigmaL) {
        if (unmPoints.Count >= 15) {
          for (let j = 14; j < unmPoints.Count; j++) {
            let subscript: number = unmPoints.Get(j);
            let unnormal = new SUnormals(subscript, EUnormals._15Points_Continous_Inside_C_Area, spcList[subscript]);
            unormList.Add(unnormal);
          }
        }
        unmPoints.Clear();
      } else {
        unmPoints.Add(i);
      }
    }
    if (unmPoints.Count >= 15) {
      if (unmPoints.Count >= 15) {
        for (let j = 14; j < unmPoints.Count; j++) {
          let subscript: number = unmPoints.Get(j);
          let unnormal = new SUnormals(subscript, EUnormals._15Points_Continous_Inside_C_Area, spcList[subscript]);
          unormList.Add(unnormal);
        }
      }
    }
  }

  let type8 = category & 128;
  if (type8 == 128) {
    //_8Points_Continous_Biside_But_Out_Of_C_Area
    unmPoints.Clear();
    for (let i = 0; i < spcList.length; i++) {
      if (spcList[i] < cl + sigma && spcList[i] > cl - sigmaL) {
        if (unmPoints.Count >= 8) {
          for (let j = 7; j < unmPoints.Count; j++) {
            let subscript: number = unmPoints.Get(j);
            let unnormal = new SUnormals(subscript, EUnormals._8Points_Continous_Biside_But_Out_Of_C_Area, spcList[subscript]);
            unormList.Add(unnormal);
          }
        }
        unmPoints.Clear();
      } else {
        unmPoints.Add(i);
      }
    }
    if (unmPoints.Count >= 8) {
      for (let j = 7; j < unmPoints.Count; j++) {
        let subscript: number = unmPoints.Get(j);
        let unnormal = new SUnormals(subscript, EUnormals._8Points_Continous_Biside_But_Out_Of_C_Area, spcList[subscript]);
        unormList.Add(unnormal);
      }
    }
  }

  return unormList;
}
